//#include "stdafx.h"
#include "ChannelForMixer.h"
#include <math.h>
#include <stdlib.h>
#include <memory.h>

CChannelForMixer::CChannelForMixer(void)
	: Volume(1.0f)
	, Pan(0.0f)
	, Position(0.0f)
	, pS(NULL)
	, PreProc(NULL)
	, Proc(NULL)
	, type(NORMAL_IN)
	, PreCtx(NULL)
	, Ctx(NULL)
	, Mute(false)
	, Invert(false)
	, IsPassBy(false)
{
}

CChannelForMixer::~CChannelForMixer(void)
{
}

int CChannelForMixer::ProcessData(float* pLChnl, float* pRChnl, int nSamples)
{
	if(nSamples<=0)
		return 0;
	float v,pan,pos;
	v=Volume,pan=Pan,pos=Position;
	float vl=((pan>0.0f)?((100.0f-pan)/100.0f):1.0f)*v,vr=((pan<0.0f)?((100.0f+pan)/100.0f):1.0f)*v;
	float pl=(pos<0.0f)?((0.0f-pos)/100.0f):0.0f,pr=(pos>0.0f)?((pos)/100.0f):0.0f;
	float t=0.0f;
	int i=0;
	bool mute=Mute;
	bool invert=Invert;
	int processed_samples=nSamples;

	try
	{
		if(type==NORMAL_IN&&pS)
		{
			processed_samples=pS->PushData(pLChnl,pRChnl,nSamples);
		}
		if(PreProc)
		{
			PreProc(pLChnl,pRChnl,processed_samples,this,PreCtx);
		}
		if((type==NORMAL_OUT||type==NORMAL_IN||type==HOST_OUT)&&mute)
		{
			memset(pLChnl,0,processed_samples*sizeof(float));
			memset(pRChnl,0,processed_samples*sizeof(float));
		}
		else
		{
			if(invert)
			{
				for(i=0;i<processed_samples;++i)
				{
					t=pLChnl[i];
					pLChnl[i]=0.0f-((pLChnl[i]*(1.0f-pr)+pRChnl[i]*pl)*vl);
					pRChnl[i]=0.0f-((pRChnl[i]*(1.0f-pl)+t*pr)*vr);
				}
			}
			else
			{
				for(i=0;i<processed_samples;++i)
				{
					t=pLChnl[i];
					pLChnl[i]=(pLChnl[i]*(1.0f-pr)+pRChnl[i]*pl)*vl;
					pRChnl[i]=(pRChnl[i]*(1.0f-pl)+t*pr)*vr;
				}
			}
		}
		if(Proc)
		{
			Proc(pLChnl,pRChnl,processed_samples,this,Ctx);
		}
		if(type==NORMAL_OUT||type==HOST_IN||type==HOST_OUT)
		{
			if(pS)
			{
				processed_samples=pS->PushData(pLChnl,pRChnl,nSamples);
			}
		}
		if(type==HOST_IN&&mute)
		{
			memset(pLChnl,0,processed_samples*sizeof(float));
			memset(pRChnl,0,processed_samples*sizeof(float));
		}
	}
	catch(...)
	{
		return i;
	}
	return processed_samples;
}

bool CChannelForMixer::BindStream(CStreamForChannel* pStream)
{
	if(pStream!=NULL)
	{
		pS=pStream;
		return true;
	}
	return false;
}

CStreamForChannel* CChannelForMixer::GetBindedStream(void)
{
	return pS;
}

float CChannelForMixer::SetVolume(float vol)
{
	Volume=vol;
	return vol;
}

float CChannelForMixer::GetVolume(void)
{
	return Volume;
}

float CChannelForMixer::SetPan(float PanPercents)
{
	if(PanPercents>100.0f)
		PanPercents=100.0f;
	if(PanPercents<-100.0f)
		PanPercents=-100.0f;
	Pan=PanPercents;
	return PanPercents;
}

float CChannelForMixer::GetPan()
{
	return Pan;
}

float CChannelForMixer::SetPosition(float PosFromLeftToRight)
{
	if(PosFromLeftToRight>100.0f)
		PosFromLeftToRight=100.0f;
	if(PosFromLeftToRight<-100.0f)
		PosFromLeftToRight=-100.0f;
	Position=PosFromLeftToRight;
	return PosFromLeftToRight;
}

float CChannelForMixer::GetPosition(void)
{
	return Position;
}

bool CChannelForMixer::SetRawDataProcess(ChannelDataCallBackProc CallBackFun,void* context)
{
	if(CallBackFun!=NULL)
	{
		PreProc=CallBackFun;
		PreCtx=context;
		return true;
	}
	return false;
}

bool CChannelForMixer::SetDataProcess(ChannelDataCallBackProc CallBackFun,void* context)
{
	if(CallBackFun!=NULL)
	{
		Proc=CallBackFun;
		Ctx=context;
		return true;
	}
	return false;
}

void CChannelForMixer::SetMute(bool fEnabled)
{
	Mute=fEnabled;
}

bool CChannelForMixer::GetMute(void)
{
	return Mute;
}

void CChannelForMixer::SetInvert(bool fEnabled)
{
	Invert=fEnabled;
}

bool CChannelForMixer::GetInvert(void)
{
	return Invert;
}